package com.fulu.game.bi.service.impl.roi;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.fulu.game.bi.common.exception.BizException;
import com.fulu.game.bi.entity.po.auth.BiUser;
import com.fulu.game.bi.entity.po.channel.Label;
import com.fulu.game.bi.entity.po.channel.LabelGroup;
import com.fulu.game.bi.entity.po.channel.RegistSource;
import com.fulu.game.bi.entity.po.channel.RegistSourceGroup;
import com.fulu.game.bi.entity.po.roi.Delivery;
import com.fulu.game.bi.entity.vo.channel.label.LabelGroupQueryVO;
import com.fulu.game.bi.entity.vo.channel.label.LabelQueryVO;
import com.fulu.game.bi.entity.vo.channel.source.RegisterSourceGroupQueryVO;
import com.fulu.game.bi.entity.vo.delivery.DeliveryDisplayVO;
import com.fulu.game.bi.entity.vo.delivery.DeliverySaveVO;
import com.fulu.game.bi.entity.vo.roi.RoiStatQueryVO;
import com.fulu.game.bi.enums.CommonlyOrderEnums;
import com.fulu.game.bi.mysql.bi.channel.LabelGroupDao;
import com.fulu.game.bi.mysql.bi.channel.RegisterSourceGroupDao;
import com.fulu.game.bi.mysql.bi.roi.DeliveryCostDao;
import com.fulu.game.bi.mysql.playadmin.channel.LabelDao;
import com.fulu.game.bi.mysql.playadmin.channel.RegistSourceDao;
import com.fulu.game.bi.redis.service.auth.BiUserService;
import com.fulu.game.bi.redis.service.roi.DeliveryCostService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeliveryCostServiceImpl implements DeliveryCostService {

    @Autowired
    private BiUserService biUserService;

    @Autowired
    private DeliveryCostDao deliveryCostDao;

    @Autowired
    private LabelDao labelDao;

    @Autowired
    private RegistSourceDao registSourceDao;

    @Autowired
    private LabelGroupDao labelGroupDao;

    @Autowired
    private RegisterSourceGroupDao registerSourceGroupDao;

    @Override
    public Delivery save(DeliverySaveVO vo) {
        if (Objects.isNull(vo.getId())) {
            return createNewDeliveryCost(vo);
        }

        return updateExistDeliveryCost(vo);
    }

    private Delivery updateExistDeliveryCost(DeliverySaveVO vo) {
        BiUser currentUser = biUserService.getCurrentUser();
        Date now = new Date();

        List<Delivery> list = checkUniq(vo);
        if (!list.stream().allMatch(delivery -> vo.getId().equals(delivery.getId()))) {
            throw new BizException("记录已存在，无法修改");
        }
        Delivery delivery = new Delivery();
        BeanUtils.copyProperties(vo, delivery);

        delivery.setUpdateAdminId(currentUser.getId());
        delivery.setUpdateAdminName(currentUser.getName());
        delivery.setUpdateTime(now);

        deliveryCostDao.updateSelective(delivery);

        log.info("添加推广花费：{}", delivery);

        return delivery;
    }

    private Delivery createNewDeliveryCost(DeliverySaveVO vo) {
        BiUser currentUser = biUserService.getCurrentUser();
        Date now = new Date();

        List<Delivery> list = checkUniq(vo);
        if (CollectionUtil.isNotEmpty(list)) {
            throw new BizException("记录已存在，请勿重复添加");
        }

        Delivery delivery = new Delivery();
        BeanUtils.copyProperties(vo, delivery);

        delivery.setCreateAdminId(currentUser.getId());
        delivery.setCreateAdminName(currentUser.getName());
        delivery.setUpdateAdminId(currentUser.getId());
        delivery.setUpdateAdminName(currentUser.getName());
        delivery.setCreateTime(now);
        delivery.setUpdateTime(now);

        deliveryCostDao.insert(delivery);

        log.info("添加推广花费：{}", delivery);

        return delivery;
    }

    private List<Delivery> checkUniq(DeliverySaveVO vo) {
        RoiStatQueryVO queryVO = new RoiStatQueryVO();
        queryVO.setRegisterSourceGroupId(vo.getRegisterSourceGroupId());
        if (Objects.nonNull(vo.getRegisterSourceId())) {
            queryVO.setRegisterSourceIdList(Collections.singletonList(vo.getRegisterSourceId()));
        }
        queryVO.setLabelGroupId(vo.getLabelGroupId());
        if (Objects.nonNull(vo.getLabelId())) {
            queryVO.setLabelIdList(Collections.singletonList(vo.getLabelId()));
        }

        DateTime dateTimeBegin = DateUtil.beginOfDay(vo.getStartTime());
        DateTime dateTimeEnd = DateUtil.endOfDay(vo.getStartTime());

        queryVO.setValidTimeEnd(dateTimeEnd);
        queryVO.setValidTimeStart(dateTimeBegin);
        return deliveryCostDao.list(queryVO);
    }

    @Override
    public PageInfo<DeliveryDisplayVO> list(RoiStatQueryVO vo) {
        Map<Integer, RegistSourceGroup> sourceGroupMap = registerSourceGroupDao.list(new RegisterSourceGroupQueryVO()).stream()
                .collect(Collectors.groupingBy(RegistSourceGroup::getId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        Map<Integer, RegistSource> sourceMap = registSourceDao.findAll().stream()
                .collect(Collectors.groupingBy(RegistSource::getId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        Map<Integer, LabelGroup> labelGroupMap = labelGroupDao.list(new LabelGroupQueryVO()).stream()
                .collect(Collectors.groupingBy(LabelGroup::getId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        Map<Integer, Label> labelMap = labelDao.list(new LabelQueryVO()).stream()
                .collect(Collectors.groupingBy(Label::getId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));

        PageHelper.startPage(vo.getPageNum(), vo.getPageSize(), CommonlyOrderEnums.UPDATE_DESC.getValue());
        List<Delivery> list = deliveryCostDao.list(vo);

        PageInfo pageInfo = new PageInfo(list);
        List<Delivery> tempList = pageInfo.getList();
        List<DeliveryDisplayVO> voList = tempList.stream()
                .map(v -> this.compute(v, sourceMap, sourceGroupMap, labelMap, labelGroupMap))
                .collect(Collectors.toList());

        pageInfo.setList(voList);
        return pageInfo;
    }

    private DeliveryDisplayVO compute(Delivery v, Map<Integer, RegistSource> sourceMap, Map<Integer, RegistSourceGroup> sourceGroupMap, Map<Integer, Label> labelMap, Map<Integer, LabelGroup> labelGroupMap) {
        DeliveryDisplayVO deliveryDisplayVO = new DeliveryDisplayVO();
        BeanUtils.copyProperties(v, deliveryDisplayVO);
        Optional.ofNullable(v.getLabelId()).map(id -> {
            Label label = labelMap.get(id);
            label = Optional.ofNullable(label).orElse(new Label());
            deliveryDisplayVO.setLabelName(label.getName());
            return 0;
        });
        Optional.ofNullable(v.getLabelGroupId()).map(id -> {
            LabelGroup labelGroup = labelGroupMap.get(id);
            labelGroup = Optional.ofNullable(labelGroup).orElse(new LabelGroup());
            deliveryDisplayVO.setLabelGroupName(labelGroup.getName());
            return 0;
        });
        Optional.ofNullable(v.getRegisterSourceGroupId()).map(id -> {
            RegistSourceGroup registSourceGroup = sourceGroupMap.get(id);
            registSourceGroup = Optional.ofNullable(registSourceGroup).orElse(new RegistSourceGroup());
            deliveryDisplayVO.setRegisterSourceGroupName(registSourceGroup.getName());
            return 0;
        });
        Optional.ofNullable(v.getRegisterSourceId()).map(id -> {
            RegistSource registSource = sourceMap.get(id);
            registSource = Optional.ofNullable(registSource).orElse(new RegistSource());
            deliveryDisplayVO.setRegisterSourceName(registSource.getName());
            return 0;
        });
        return deliveryDisplayVO;
    }

}
